﻿Imports org.model.lib
Imports IICBusinessLogic.PeriodProcessing
Imports IICBusinessLogic



''' <summary>
''' tests grade change of processed periods
''' </summary>
''' <remarks></remarks>
''' 
<TestClass()>
Public Class TestGradeChange

    <TestMethod()>
    Public Sub changeGradeFromPassToFail()

        ModelContext.newForUnitTests()
        Dim dc As PeriodProcessor
        Dim maxPeriodDate As Date = _
            ModelContext.CurrentDBUtils.getDtValue("select max(periodDate) from [Period]")

        Try
            ModelContext.beginTrans()
            PeriodProcessorTestUtils.initialize()
            'create a period, 2 students passing marks
            Dim diploma As DiplomaType = PeriodProcessorTestUtils.createDiplomaWithXCertReq(1)

            'create 2 lessons
            Dim lessons As List(Of Lesson) = New List(Of Lesson)
            For i As Integer = 1 To 2
                lessons.Add(PeriodProcessorTestUtils.CreateLesson(100, 70))
            Next

            LessonDataUtils.saveLesson(lessons.ToArray)

            'add lesson 0 as a requirement 
            diploma.DiplomaRequirements(0).Certification.AddLessonRequirement(lessons(0), False)
            'add lesson1 as a requirement 
            diploma.DiplomaRequirements(0).Certification.AddLessonRequirement(lessons(1), False)

            DiplomaTypeDataUtils.saveDiplomaType(diploma)

            Dim stud As Student = StudentDataUtils.findByKey(10) 'get a random student
            Dim stud2 As Student = StudentDataUtils.findByKey(9) 'get a second random student
            Dim diplEarned As Integer = stud2.DiplomasEarned.Count
            Dim certEarned As Integer = stud2.CertificationsEarned.Count

            'create a Period of classes
            Dim period As Period = PeriodFactory.Create
            period.DiplomaSuperTypeId = PeriodProcessorTestUtils.diplomaSuperType.DiplomaSuperTypeId
            period.PeriodDate = DateAdd(DateInterval.Month, 1, maxPeriodDate)
            period.PeriodCode = "59" & ModelContext.CurrentDBUtils.getIntValue("select count(*)+1 from period")

            Dim pername As String = period.PeriodName
            PeriodDataUtils.savePeriod(period)

            Dim pc1 As PeriodClass = PeriodProcessorTestUtils.CreateClassAndAddStudentsAsClassMembers( _
                                        lessons(0), period, stud, stud2)
            Dim pc2 As PeriodClass = PeriodProcessorTestUtils.CreateClassAndAddStudentsAsClassMembers( _
                                    lessons(1), period, stud, stud2)

            pc1.Members(0).Grade = 100
            pc2.Members(0).Grade = 100

            pc1.Members(1).Grade = 100
            pc2.Members(1).Grade = 100

            Dim modClassMember As ClassMember = pc2.Members(1)
            modClassMember.Grade = 100

            PeriodClassDataUtils.savePeriodClass(pc1)
            PeriodClassDataUtils.savePeriodClass(pc2)
            'now we see if student1 above has earned the diploma as expected
            dc = New PeriodProcessor(period)
            dc.processPeriodAndStoreToDatabase()
            Dim tstPeriodProcessId As Integer = dc.PeriodProcess.PeriodProcessId
            'make sure 2 students earned certificates
            Assert.AreEqual(2, dc.diplomasEarned.Count)

            StudentDataUtils.reload(stud)
            StudentDataUtils.reload(stud2)
            Assert.IsTrue(stud2.DiplomasEarned.Count = diplEarned + 1, "Expected student to have earned one addtional diploma")
            Assert.IsTrue(stud2.CertificationsEarned.Count = certEarned + 1, "Expected student to have earned one addtional certification")

            Assert.IsNotNull(stud2.getDiplomaEarned(diploma), "Student should passed diploma")
            Assert.IsNotNull(stud.getDiplomaEarned(diploma), "Student should passed diploma")

            Dim dic As New Dictionary(Of Integer, Integer)
            dic.Add(dc.diplomasEarned(0).StudentId.GetValueOrDefault, dc.diplomasEarned(0).SerialNo.GetValueOrDefault)
            dic.Add(dc.diplomasEarned(1).StudentId.GetValueOrDefault, dc.diplomasEarned(1).SerialNo.GetValueOrDefault)

            'now modify mark of 2nd student to nothing (not attend) 
            'reload from database
            modClassMember = ClassMemberDataUtils.findByKey(modClassMember.ClassMemberId)
            modClassMember.addValidator(New GradeChangedValidator)
            'the GradeChangedValidator will also reverse any certificates earned
            modClassMember.Grade = Nothing
            ClassMemberDataUtils.saveClassMember(modClassMember)

            ClassMemberDataUtils.reload(modClassMember)
            Assert.IsTrue(modClassMember.PeriodProcessId Is Nothing, _
                          "After grade change to not pass, period process id should be null, for classMember:" & modClassMember.ClassMemberId)
            Assert.IsNull(ClassMemberDataUtils.findOne("PeriodProcessId={0} and studentId={1}", _
                                                      tstPeriodProcessId, modClassMember.StudentId))
            'check that periodprocessid was set to null
            StudentDataUtils.reload(stud2)
            StudentDataUtils.reload(stud)

            'make sure that the diploma was reversed
            Assert.IsNull(stud2.getDiplomaEarned(diploma), "Student should no longer have the diploma passed")
            Assert.IsTrue(stud2.DiplomasEarned.Count = diplEarned)
            Assert.IsTrue(stud2.CertificationsEarned.Count = certEarned)

            'make sure that other students kept their serial numbers
            Dim dearned As DiplomaEarned = stud.getDiplomaEarned(diploma)
            Assert.IsNotNull(dearned)
            Assert.AreEqual(dearned.SerialNo, dic(stud.StudentId), "Expected student to have kept the serial number")
            Assert.IsTrue(dearned.DiplomaSatisfiedRequirements.Count = 1)


            'now change back the grade to a passing mark
            modClassMember = ClassMemberDataUtils.findByKey(modClassMember.ClassMemberId)
            modClassMember.addValidator(New GradeChangedValidator)
            'the GradeChangedValidator will also reverse any certificates earned
            modClassMember.Grade = 100
            ClassMemberDataUtils.saveClassMember(modClassMember)
            Trace.TraceInformation("Will reprocess period after change of grade to 100")
            'now re-process period
            dc = New PeriodProcessor(period)
            dc.processPeriodAndStoreToDatabase()

            'check that student now has eaned the diploma/certificate
            StudentDataUtils.reload(stud)
            StudentDataUtils.reload(stud2)

            'make sure that the diploma was earned back
            Dim stud2DiplomaEarned As DiplomaEarned = stud2.getDiplomaEarned(diploma)
            Assert.IsNotNull(stud2DiplomaEarned, "Student has passed the diploma")
            Assert.IsNotNull(stud.getDiplomaEarned(diploma), "Student has passed the diploma")

            Assert.IsTrue(stud2.DiplomasEarned.Count = diplEarned + 1)
            Assert.IsTrue(stud2.CertificationsEarned.Count = certEarned + 1)

            'rollback so we do not save to the database
            ModelContext.rollbackTrans()

        Finally

            ModelContext.rollbackTrans()
            ModelContext.release()

        End Try
    End Sub


    '<TestMethod()>
    'Public Sub UpdateClassReportDescriptions()

    '    Try
    '        Model.ModelContext.CurrentUser = New Model.ModelObjectPrincipal("test")
    '        Dim pupdate As New PeriodClassDBUpdateHandler
    '        Dim peridos As List(Of PeriodClass) = PeriodClassDataUtils.findList("periodid in (select periodid from period where [DiplomaSuperTypeId] in (2,5))")

    '        For Each pc As PeriodClass In peridos
    '            pc.loadGradeMappings()
    '            pupdate.save(pc)
    '        Next

    '    Finally
    '        Model.ModelContext.release()
    '    End Try

    'End Sub

End Class
